// #include "../SLIC/utils.hpp"
#include <iostream>
// #include <x86intrin.h>

// #define _GNU_SOURCE /* These two lines are optional. They are only needed to   \
//                        use the scalar */
#include <math.h> /* functions sin, exp, sincos,...                                       */

// __m256d _ZGVdN4vv_pow(__m256d x, __m256d y);
extern "C" {
#include "help.h"
}


using namespace std;
int main() {
  const double constant1 = 3294.6;
  const double constant2 = 1 / 269.025;
  const double constant3 = 0.055 / 1.055;
  const double constant4 = 2.4;
  const double constant5 = 255.0 * 0.04045;
  __m256d mm_constant1 = _mm256_broadcast_sd(&constant1);
  __m256d mm_constant2 = _mm256_broadcast_sd(&constant2);
  __m256d mm_constant3 = _mm256_broadcast_sd(&constant3);
  __m256d mm_constant4 = _mm256_broadcast_sd(&constant4);
  __m256d mm_constant5 = _mm256_broadcast_sd(&constant5);

  double dx[4];
  //   double* dx = align_new<double>(4, 32);
  dx[0] = 100.0;
  dx[1] = 3.0;
  dx[2] = 600.0;
  dx[3] = 7.0;
  __m256d mm_r = _mm256_load_pd(dx);
  //   mm_r =  _mm256_cmp_pd(mm_r, mm_constant5, _CMP_LE_OQ);
  mm_r = _mm256_blendv_pd(
      _mm256_div_pd(mm_r, mm_constant1),
      _ZGVdN4vv_pow(_mm256_fmadd_pd(mm_r, mm_constant2, mm_constant3),
                    mm_constant4),
      _mm256_cmp_pd(mm_r, mm_constant5, _CMP_GT_OQ));
  _mm256_store_pd(dx, mm_r);
  for (int i = 0; i < 4; i++)
    cout << dx[i] << endl;
  double dy[4] = {100.0, 3.0, 600.0, 7.0};
  for (int i = 0; i < 4; i++) {
    if (dy[i] <= constant5)
      dy[i] = dy[i] / 3294.6;
    else
      dy[i] = pow(dy[i] / 269.025 + 0.055 / 1.055, 2.4);
  }
  for (int i = 0; i < 4; i++)
    cout << dy[i] << endl;
}